/*
 usage information:

 this is a test foo bar


 This library provides functionality for log messages and asserts by
  exposing a number of functions which, if not activated by calling
  their activation functions, they cause no actions.

  Logger:

 Logger.debug(<message>)
 Logger.info(<message>)
 Logger.warn(<message>)
 Logger.error(<message>)

  it is activated by calling the Logger.level function:

 Logger.level(
     [Logger.NONE|Logger.DEBUG|Logger.INFO|Logger.WARN|Logger.ERROR])
 eg:

 Logger.level(Logger.DEBUG);

 By default, log level is set to none. In this mode, none of the above
   log messages result in anything being printed to the console.

 Setting the log lovel to anything other than none results in all log
   messages at that level or higher printing to console.

 For example:

 Logger.level(Logger.INFO);
 Logger.debug("this is a debug message");
 Logger.info("this is a info message");
 Logger.error("this is an error message");

 Would result in the following console output:
   this is a info message
   this is an error message


 Assert:

 Assert.assertDefined(<var>, [message])
 Assert.assertNotEquals(<var1>, <var2>, [message])
 Assert.assertEquals(<var1>, <var2>, [message])
 Assert.assert(<condition>, [message])

 Assert.assertsOff();
 Assert.assertsOn();

*/
initDevMode = function() {
  Logger.initDevMode();
  Assert.initDevMode()
};
function randomString(length) {
  var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
  var randomstring = "";
  for(var i = 0;i < length;i++) {
    var rnum = Math.floor(Math.random() * chars.length);
    randomstring += chars.substring(rnum, rnum + 1)
  }
  return randomstring
}
;(function(window) {
  var assertBuilder = function() {
    var that = {};
    that.assertDefined = function(a, msg) {
    };
    that.assertNotNull = function(a, msg) {
    };
    that.assertNotEquals = function(a, b, msg) {
    };
    that.assertEquals = function(a, b, msg) {
    };
    that.assert = function(test, msg) {
    };
    that.assertsOff = function() {
      that.assertDefined = function(a, msg) {
      };
      that.assertNotEquals = function(a, b, msg) {
      };
      that.assertEquals = function(a, b, msg) {
      };
      that.assert = function(test, msg) {
      }
    };
    that.assertsOn = function() {
      that.assertDefined = function(a, msg) {
        msg = msg || "expected argument to be defined.";
        if(typeof a == "undefined") {
          that.assert(false, msg)
        }
      };
      that.assertNotNull = function(a, msg) {
        msg = msg || "expected argument to be not null.";
        if(a == null) {
          that.assert(false, msg)
        }
      };
      that.assertNotEquals = function(a, b, msg) {
        msg = msg || "expected not" + a + " but got " + b + " instead.";
        that.assert(a != b, msg)
      };
      that.assertEquals = function(a, b, msg) {
        msg = msg || "expected " + a + " but got " + b + " instead.";
        that.assert(a == b, msg)
      };
      that.assert = function(test, msg) {
        msg = msg || "(no error message)";
        if(!test) {
          throw"Assertion failed with: " + msg;
        }
      }
    };
    return that
  };
  this["Assert"] = assertBuilder();
  this["initDevMode"] = initDevMode;
  window.randomString = randomString
})(window);
(function(window) {
  var loggerBuilder = function() {
    var that = {};
    that.DEBUG = 0;
    that.INFO = 1;
    that.WARN = 2;
    that.ERROR = 3;
    that.NONE = 10;
    that.error = function(msg) {
    };
    that.warn = function(msg) {
    };
    that.debug = function(msg) {
    };
    that.info = function(msg) {
    };
    that.logsOff = function() {
      that.error = function(msg) {
      };
      that.warn = function(msg) {
      };
      that.debug = function(msg) {
      };
      that.info = function(msg) {
      }
    };
    that.logsOff();
    that.level = function level(mode) {
      if(typeof mode == "undefined") {
        mode = that.DEBUG
      }
      ERROR_TEST = false;
      ERROR = false;
      WARN = false;
      INFO = false;
      DEBUG = false;
      that.logsOff();
      if(mode == that.DEBUG) {
        ERROR = true;
        WARN = true;
        INFO = true;
        DEBUG = true
      }else {
        if(mode == that.INFO) {
          ERROR = true;
          WARN = true;
          INFO = true
        }else {
          if(mode == that.WARN) {
            ERROR = true;
            WARN = true
          }else {
            if(mode == that.ERROR) {
              ERROR = true
            }
          }
        }
      }
      that.setupLogs()
    };
    that.setupLogs = function() {
      var consoleLogBindSupport = false;
      var consoleLogSupport = false;
      if(window.console) {
        if(window.console.log) {
          consoleLogSupport = true;
          if(window.console.bind) {
            consoleLogBindSupport = true
          }
        }
      }
      var consoleErrorBindSupport = false;
      var consoleErrorSupport = false;
      if(window.console) {
        if(window.console.error) {
          consoleErrorSupport = true;
          if(window.console.error.bind) {
            consoleErrorBindSupport = true
          }
        }
      }
      if(ERROR_TEST) {
        if(typeof console.error == "function") {
          that.error = function(msg) {
            var caller = arguments.callee.caller;
            var myArguments = arguments;
            myArguments.callee = caller.caller.caller.caller;
            console.trace.apply(console, myArguments);
            var getStackTrace = function() {
              var obj = {};
              Error.captureStackTrace(obj, getStackTrace);
              return obj.stack
            };
            var trace = getStackTrace();
            console.log("bar:" + trace[2])
          }
        }else {
          msg = "[ERROR] " + msg;
          that.error = function(msg) {
            setTimeout(function() {
              throw new Error(msg);
            }, 0)
          }
        }
      }
      if(ERROR) {
        if(consoleErrorBindSupport) {
          that.error = console.error.bind(console)
        }else {
          that.error = function(msg) {
            msg = "[ERROR] " + msg;
            setTimeout(function() {
              throw new Error(msg);
            }, 0)
          }
        }
      }
      if(WARN) {
        if(consoleErrorBindSupport) {
          that.warn = console.error.bind(console)
        }else {
          that.warn = function(msg) {
            msg = "[WARN] " + msg;
            setTimeout(function() {
              throw new Error(msg);
            }, 0)
          }
        }
      }
      if(INFO) {
        if(consoleLogBindSupport) {
          that.info = console.log.bind(console)
        }else {
          if(consoleLogSupport) {
            that.info = function(message) {
              console.log(message)
            }
          }
        }
      }
      if(DEBUG) {
        if(consoleLogBindSupport) {
          that.debug = console.log.bind(console)
        }else {
          if(consoleLogSupport) {
            that.debug = function(message) {
              console.log(message)
            }
          }
        }
      }
    };
    return that
  };
  initDevMode = function() {
    Logger.initDevMode();
    Assert.initDevMode()
  };
  function randomString(length) {
    var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
    var randomstring = "";
    for(var i = 0;i < length;i++) {
      var rnum = Math.floor(Math.random() * chars.length);
      randomstring += chars.substring(rnum, rnum + 1)
    }
    return randomstring
  }
  loggerBuilder.fn = loggerBuilder.prototype = {constructor:loggerBuilder};
  this["Logger"] = loggerBuilder()
})(window);
